﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WPLDB.DA.Models;
using WPLDB.DA.Interfaces;
using WPLDB.Utility.Extensions;

namespace WPLDB.Code
{
    /// <summary>
    /// This class helps to created Helper Class C# code 
    /// and variables naming are not explicit required the explanations
    /// </summary>
    public class CreateHelperClassCode : ICreateClassCode
    {

        #region "Variables"
        private List<TableModel> _listOfTableModel;
        private string _database;
        private string _className;
        private string _namespace;
        private string _fileName;

        #endregion

        #region "ctor"

        public CreateHelperClassCode(List<TableModel> listOfTableModel, string database, string className, string nameSpace, string fileName)
        {
            _listOfTableModel = listOfTableModel;
            _database = database.RemoveSpecialChar();
            _className = className.RemoveSpecialChar();
            _namespace = nameSpace;
            _fileName = fileName;
        }

        #endregion

        #region "Constants"
        string CLASS = "[COMMENT1][NEWLINE][NEWLINE]using System;[NEWLINE]using System.ComponentModel;[NEWLINE]using [PROPERTYTYPE].[THISKEY].Designer;[NEWLINE]" +
                        "[NEWLINE]namespace [PROPERTYTYPE][NEWLINE]" +
                        "{" +
                        "[NEWLINE][T]public sealed class [CLASSNAME]Helper[NEWLINE]" +
                        "[T]{[NEWLINE]" +
                        "[T][T]/// <summary>[NEWLINE]" +
                        "[T][T]/// Database file name[NEWLINE]" +
                        "[T][T]/// </summary>[NEWLINE]" +
                        "[T][T]public static readonly string ConnectionString = \"Data Source=isostore:/[PROPERTY].sdf\";[NEWLINE]" +
                        "[NEWLINE]" +
                        "[T][T]private static readonly [CLASSNAME]Helper _[CLASSNAME]Helper = new [CLASSNAME]Helper();[NEWLINE]" +
                        "[NEWLINE]" +
                        "[T][T]private [CLASSNAME]Helper() { }[NEWLINE]" +
                        "[NEWLINE]" +
                        "[T][T]public static [CLASSNAME]Helper Instance()[NEWLINE]" +
                        "[T][T]{[NEWLINE]" +
                        "[T][T][T]return _[CLASSNAME]Helper;[NEWLINE]" +
                        "[T][T]}[NEWLINE]" +
                        "[NEWLINE]" +
                        "[T][T]public bool CreateInitialData()[NEWLINE]" +
                        "[T][T]{[NEWLINE]" +
                        "[NEWLINE]" +
                        "[T][T][T]BackgroundWorker backgroundWorker = new BackgroundWorker();[NEWLINE]" +
                        "[T][T][T]backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);[NEWLINE]" +
                        "[NEWLINE]" +
                        "[T][T][T]backgroundWorker.RunWorkerAsync();[NEWLINE]" +
                        "[NEWLINE]" +
                        "[T][T][T]return true;[NEWLINE]" +
                        "[T][T]}[NEWLINE]" +
                        "[T][T]/// <summary>[NEWLINE]" +
                        "[T][T]/// This method create new database if not exist and also help code for inserting initial data in the table.[NEWLINE]" +
                        "[T][T]/// </summary>[NEWLINE]" +
                        "[T][T]void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)[NEWLINE]" +
                        "[T][T]{[NEWLINE]" +
                        "[T][T][T]using ([CLASSNAME] context = new [CLASSNAME](ConnectionString))[NEWLINE]" +
                        "[T][T][T]{[NEWLINE]" +
                        "[T][T][T][T]if (!context.DatabaseExists())[NEWLINE]" +
                        "[T][T][T][T]{[NEWLINE]" +
                        "[NEWLINE]" +
                        "[T][T][T][T][T]context.CreateDatabase();[NEWLINE]" +
                        "[NEWLINE]" +
                        "[NEWLINE][T][T][T][T][T]#region Insert actual data in this section[NEWLINE]" +
                        "[LISTOFPROPERTIES]" +
                        "[NEWLINE][T][T][T][T][T]#endregion[NEWLINE]" +
                        "[NEWLINE]" +
                        "[NEWLINE][T][T][T][T][T]try[NEWLINE]" +
                        "[T][T][T][T][T]{[NEWLINE]" +
                        "[T][T][T][T][T][T]context.SubmitChanges();[NEWLINE]" +
                        "[T][T][T][T][T]}[NEWLINE]" +
                        "[T][T][T][T][T]catch (Exception)[NEWLINE]" +
                        "[T][T][T][T][T]{[NEWLINE]" +
                        "[T][T][T][T][T][T]//Initial Data insertion is unsuccessful then delete the database.[NEWLINE]" +
                        "[T][T][T][T][T][T]context.DeleteDatabase();[NEWLINE]" +
                        "[T][T][T][T][T][T]throw;[NEWLINE]" +
                        "[T][T][T][T][T]}[NEWLINE]" +
                        "[T][T][T][T]}[NEWLINE]" +
                        "[T][T][T]}[NEWLINE]" +
                        "[T][T]}[NEWLINE]" +
                        "[T]}[NEWLINE]" +
                        "}[NEWLINE]";

        string INSERTONSUBMIT = "[NEWLINE][T][T][T][T][T]context.[PROPERTYPLURAL].InsertOnSubmit([NEWLINE]" +
                                "[T][T][T][T][T][T]new [PROPERTYSINGULAR][NEWLINE]" +
                                "[T][T][T][T][T][T]{" +
                                "[LISTOFPROPERTIES]" +
                                "[NEWLINE][T][T][T][T][T][T]});[NEWLINE]";

        string COLUMNINFO = "[NEWLINE][T][T][T][T][T][T][T]{0} = new {1},";

        string COMMENT1 = "//------------------------------------------------------------------------------[NEWLINE]" +
                           "// <auto-enerated>[NEWLINE]" +
                           "//    This code was generated from a template.[NEWLINE]" +
                           "//[NEWLINE]" +
                           "//    This class helps to initiate the database into isostore and create initial data into the table.[NEWLINE]" +
                           "//    Insert actual data in the below 'backgroundWorker_DoWork' section to code run successfully.[NEWLINE]" +
                           "// </auto-generated>[NEWLINE]" +
                           "//------------------------------------------------------------------------------[NEWLINE]";

        #endregion

        #region "Private Method"

        private string GetInitialization(string type)
        {

            string newInit = string.Empty;

            switch (type.ToUpper())
            {
                case "STRING":
                    newInit = type + "('S', 1)";
                    break;
                case "BYTE[]":
                    newInit = "Byte[1]";
                    break;
                default:
                    newInit = type + "()";
                    break;
            }

            return newInit;
        }

        #endregion

        #region "Interface Implementation"

        public string GenerateClassString()
        {
            StringBuilder insert = new StringBuilder();
            StringBuilder cols = new StringBuilder();

            if (null != _listOfTableModel)
                foreach (var table in _listOfTableModel)
                {
                    cols.Clear();
                    if (null != table && null != table.ListOfColumns)
                        foreach (var column in table.ListOfColumns)
                            cols.Append(string.Format(COLUMNINFO, column.Name.RemoveSpecialChar().ReplaceCSharpKeyWords(), GetInitialization(column.Type)));

                    if (cols.ToString().IsNotNullOrNotEmpty())
                        insert.Append(INSERTONSUBMIT
                            .ReplacePropertyPlural(table.Name.Plural)
                            .ReplacePropertySingular(table.Name.Singular)
                            .ReplaceListOfProperties(cols.ToString().RemoveLastChar())
                            .ReplaceNewLine());
                }

            return CLASS
                .ReplaceClass(_className)
                .ReplaceProperty(_database)
                .ReplacePropertyType(_namespace)
                .ReplaceListOfProperties(insert.ToString())
                .ReplacePropertyThisKey(_fileName)
                .ReplaceComment(COMMENT1, 1)
                .Replace_at()
                .ReplaceNewLine();

        }

        #endregion
    }
}
